#include "invocation_matcher.hpp"

using std::vector;
using std::tr1::shared_ptr;

namespace vimock {
_invocation_matcher::_invocation_matcher(object expected_obj,
		object expected_func, argument_matcher_vector expected_argument_matchers) :
	expected_obj(expected_obj), expected_func(expected_func),
			expected_argument_matchers(expected_argument_matchers) {
}

bool _invocation_matcher::object_matches(invocation invocation) const {
	object actual_obj = invocation->get_object();
	return expected_obj.equals(actual_obj);
}

bool _invocation_matcher::function_matches(invocation invocation) const {
	object actual_func = invocation->get_function();
	return expected_func.equals(actual_func);
}

bool _invocation_matcher::arguments_count_matches(object_vector arguments) const {
	return expected_argument_matchers->size() == arguments->size();
}

bool _invocation_matcher::arguments_content_match(object_vector arguments) const {
	vector<object>::iterator arg_iter = arguments->begin();
	vector<argument_matcher>::iterator arg_matcher_iter =
			expected_argument_matchers->begin();
	vector<argument_matcher>::iterator end_arg_matcher_iter =
			expected_argument_matchers->end();
	for (; arg_matcher_iter != end_arg_matcher_iter;
			++arg_matcher_iter, ++arg_iter) {
		argument_matcher arg_matcher(*arg_matcher_iter);
		object arg = *arg_iter;
		if (!arg_matcher->matches(arg)) {
			return false;
		}
	}
	return true;
}

bool _invocation_matcher::arguments_match(invocation invocation) const {
	object_vector arguments = invocation->get_arguments();
	if (!arguments_count_matches(arguments)) {
		return false;
	}
	if (!arguments_content_match(arguments)) {
		return false;
	}
	return true;
}

bool _invocation_matcher::matches(invocation invocation) const {
	if (!object_matches(invocation)) {
		return false;
	}
	if (!function_matches(invocation)) {
		return false;
	}
	if (!arguments_match(invocation)) {
		return false;
	}
	return true;
}
}
